#include <Windows.h>
#include <tchar.h>
#define JMP( frm, to ) ( ( ( int )to - ( int )frm ) - 5 )

HWND    hwndClient = NULL;
HMODULE hLibModule = NULL;
DWORD   SendRet    = NULL;
DWORD   RecvRet    = NULL;

void __stdcall SendPacket( DWORD nSize, PVOID lpData ) {
  COPYDATASTRUCT cds = {0};

  cds.cbData = nSize;
  cds.lpData = lpData;
  cds.dwData = 1;

  SendMessage( hwndClient, WM_COPYDATA, NULL, ( LPARAM )&cds );
}

void __stdcall RecvPacket( DWORD nSize, PVOID lpData ) {
  COPYDATASTRUCT cds = {0};

  cds.cbData = nSize;
  cds.lpData = lpData;
  cds.dwData = 0;

  SendMessage( hwndClient, WM_COPYDATA, NULL, ( LPARAM )&cds );
}

__declspec( naked ) void SendHookProc() {
  __asm {
    push ebp
    mov ebp, esp

    mov eax, [ebp+0x0C]
    mov ecx, [ebp+0x10]
    push eax
    push ecx

    call SendPacket

    jmp [SendRet]
  }
}

__declspec( naked ) void RecvHookProc() {
  __asm {
    push ebp
    mov ebp, esp

    mov eax, [ebp+0x0C]
    mov ecx, [ebp+0x10]
    push eax
    push ecx

    call RecvPacket

    jmp [RecvRet]
  }
}

void WriteJMP( DWORD from, DWORD to ) {
  DWORD flOldProtect = 0;

  VirtualProtect( ( LPVOID )from, 5, PAGE_EXECUTE_READWRITE, &flOldProtect );
  *( BYTE* )from          = 0xE9;
  *( DWORD* )( from + 1 ) = JMP( from, to );
  VirtualProtect( ( LPVOID )from, 5, flOldProtect, &flOldProtect );
}

void Init( HWND hwndInit ) {
  HANDLE hWinsock = NULL;
  hwndClient      = hwndInit;

  hWinsock = GetModuleHandle( _T("Ws2_32.dll") );

  if( hWinsock == NULL ) {
    MessageBox( NULL, _T("Winsock library non-existent"), NULL, MB_OK | MB_ICONEXCLAMATION );
    FreeLibraryAndExitThread( hLibModule, 0 );
  } else {
    DWORD lpSend = ( DWORD )GetProcAddress( ( HMODULE )hWinsock, "send" );
    SendRet      = lpSend + 5;
    WriteJMP( lpSend, ( DWORD )SendHookProc );

    DWORD lpRecv = ( DWORD )GetProcAddress( ( HMODULE )hWinsock, "recv" );
    RecvRet      = lpRecv + 5;
    WriteJMP( lpRecv, ( DWORD )RecvHookProc );
  }
}

BOOL WINAPI DllMain( HANDLE hinstDLL, DWORD dwReason, LPVOID lpvReserved ) {
  switch( dwReason ) {
    case DLL_PROCESS_ATTACH: {
      hLibModule = ( HMODULE )hinstDLL;
      break;
    }
    default:
      return false;
  }

  return true;
}